package com.jsyl.lwbk.business.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jsyl.lwbk.business.domain.*;
import com.jsyl.lwbk.business.domain.education.ChildReport;
import com.jsyl.lwbk.business.dto.AnswerDTO;
import com.jsyl.lwbk.business.dto.ChildAnswerDTO;
import com.jsyl.lwbk.business.dto.QuestionAnswerDTO;
import com.jsyl.lwbk.business.dto.QuestionDTO;
import com.jsyl.lwbk.business.handle.CalculateEvaluateScoreHandle;
import com.jsyl.lwbk.business.handle.ReportsHandle;
import com.jsyl.lwbk.business.mapper.*;
import com.jsyl.lwbk.business.mapper.education.ChildMonthPlanMapper;
import com.jsyl.lwbk.business.service.IChildRecordService;
import com.jsyl.lwbk.common.exception.BusinessException;
import com.jsyl.lwbk.common.utils.DateUtils;
import com.jsyl.lwbk.common.utils.StringUtils;
import com.jsyl.lwbk.system.mapper.SysDictDataMapper;
import com.jsyl.lwbk.system.service.ISysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class ChildRecordServiceImpl implements IChildRecordService {

    @Autowired
    ReportsHandle reportsHandle;

    @Autowired
    EvaluateRecordMapper evaluateRecordMapper;

    @Autowired
    QuestionMapper questionMapper;

    @Autowired
    ChildMapper childMapper;

    @Autowired
    EvaluateReportMapper evaluateReportMapper;

    @Autowired
    CalculateEvaluateScoreHandle calculateEvaluateScoreHandle;

    @Autowired
    ISysConfigService sysConfigService;

    @Autowired
    EvaluateAnswerOldMapper evaluateAnswerOldMapper;

    @Autowired
    EvaluateRecordOldMapper evaluateRecordOldMapper;

    @Autowired
    ReportUrlOldMapper reportUrlOldMapper;

    @Autowired
    SysDictDataMapper sysDictDataMapper;

    @Autowired
    EvaluateScoreNowMapper evaluateScoreNowMapper;

    @Autowired
    EvaluateScoreMapper evaluateScoreMapper;
    @Autowired
    private ChildMonthPlanMapper childMonthPlanMapper;
//    @Autowired
//    private ChildEvaluateSender childEvaluateSender;

    @Override
    public String saveChildRecord(ChildAnswerDTO childAnswerDTO, String teacherName) {
        Child child = childMapper.selectById(childAnswerDTO.getChildId());
        child.setCenterId(Long.valueOf(childAnswerDTO.getSelectCenterId()));
        String evaluateNumber = "";
        //如果没有编号，那就是新的一次测评做题
        if (StringUtils.isEmpty(childAnswerDTO.getEvaluateNumber())) {
            //生成新的测评编号
            evaluateNumber = DateUtils.dateTimeNow() + (int) (Math.random() * 9000 + 1000);
            List<QuestionDTO> questionList = questionMapper.selectAllQuestion();
//            Map<String, QuestionDTO> questionDTOMap = new HashMap<>();
//            for (QuestionDTO questionDTO : questionList) {
//                questionDTOMap.put(questionDTO.getId() + "", questionDTO);
//            }

            Map<String, QuestionAnswerDTO> questionAnswerDTOMap = new HashMap<>();
            for (QuestionAnswerDTO questionAnswerDTO : childAnswerDTO.getList()) {
                questionAnswerDTOMap.put(questionAnswerDTO.getQuestionId(), questionAnswerDTO);
            }

            //保存档案表
            saveEvaluateReport(child, evaluateNumber, teacherName);
            //保存做题记录
            saveEvaluateRecord(questionList, questionAnswerDTOMap, teacherName, child, evaluateNumber);
        } else {
            evaluateNumber = childAnswerDTO.getEvaluateNumber();
            //根据测评编号+题目号 更新题目，答案
            EvaluateReport evaluateReport = evaluateReportMapper.findByEvaluateNumber(childAnswerDTO.getEvaluateNumber());
            if (evaluateReport.getStatus() != 1) {
                throw new BusinessException("测评已完成或关闭，无法更新");
            }
            updateEvaluateRecord(childAnswerDTO.getList(), child, teacherName, childAnswerDTO.getEvaluateNumber());
        }
        //判断是否完成所有题目，更新测评，生成报告
        if (evaluateRecordMapper.selectUnFinishQuestion(evaluateNumber) < 1) {
            calculateEvaluateScoreHandle.handle(evaluateNumber, teacherName);
            //插入学生报告表
            ChildReport childReport =new ChildReport();
            childReport.setReportType(4);
            childReport.setTrainingProgramNumber(DateUtils.getDate());
            childReport.setChildId(childAnswerDTO.getChildId());
            childReport.setEvaluateNumber(evaluateNumber);
            childReport.setCreateBy(teacherName);
            childReport.setCreateTime(DateUtils.getNowDate());
            childReport.setUpdateBy(teacherName);
            childReport.setUpdateTime(DateUtils.getNowDate());
            childReport.setCenterId(childAnswerDTO.getSelectCenterId());
            childReport.setStatus(0);
            this.childMonthPlanMapper.insert(childReport);
            //同步至jms
//            Map map =new HashMap();
//            map.put("childId",childAnswerDTO.getChildId());
//            map.put("centerId",childAnswerDTO.getSelectCenterId());
//            childEvaluateSender.sender(map);

        }

        return evaluateNumber;
    }

    /**
     * 旧数据处理
     */
    @Override
    public void saveOldChildRecord() {
        List<EvaluateRecordOld> recordOldList = evaluateRecordOldMapper.findAll();
        String evaluateNumber = DateUtils.dateTimeNow() + (int) (Math.random() * 9000 + 1000);
        Long reportId = null;
        /*
         * 根据旧数据中的reportId可以确定是哪一次的做题记录，通过这个再新表中创建测评编号
         * 在旧测评中由于测评题目类型没办法跟新的对应上而且存的是中文，所以这边暂时没有存入
         */
        for (EvaluateRecordOld recordOld : recordOldList) {
            try {
                Child child = childMapper.selectById(recordOld.getChildId());
                if (reportId == null) {
                    reportId = recordOld.getReportId();
                    EvaluateReport report = new EvaluateReport();
                    report.setChildId(recordOld.getChildId());
                    report.setEvaluateNumber(evaluateNumber);
                    report.setCenterId(child.getCenterId());
                    report.setStatus(0);
                    report.setEvaluateVersion(1);
                    // url通过旧表中的reportId去匹配t_report_url表中的reportId存入url
                    ReportUrlOld reportUrlOld = reportUrlOldMapper.findByReportId(recordOld.getReportId());
                    if (null != reportUrlOld) {
                        report.setEvaluateUrl(reportUrlOld.getUrl());
                        report.setCreateTime(recordOld.getCreateTime());
                        report.setCreateBy(recordOld.getCreateBy());
                        evaluateReportMapper.insert(report);
                    }
                } else {
                    if (!reportId.equals(recordOld.getReportId())) { // 如果不相等则代表是下一份报告，上面查询分数有按照报告id进行排序
                        // 新的报告则在report中保存一份，并生成新的测评编号
                        reportId = recordOld.getReportId();
                        evaluateNumber = DateUtils.dateTimeNow() + (int) (Math.random() * 9000 + 1000);
                        EvaluateReport report = new EvaluateReport();
                        report.setChildId(recordOld.getChildId());
                        report.setEvaluateNumber(evaluateNumber);
                        report.setCenterId(child.getCenterId());
                        report.setStatus(1);
                        report.setEvaluateVersion(1);
                        // url通过旧表中的reportId去匹配t_report_url表中的reportId存入url
                        ReportUrlOld reportUrlOld = reportUrlOldMapper.findByReportId(recordOld.getReportId());
                        if (null != reportUrlOld) {
                            report.setStatus(0);
                            report.setEvaluateUrl(reportUrlOld.getUrl());
                            report.setCreateTime(recordOld.getCreateTime());
                        }
                        evaluateReportMapper.insert(report);
                    }
                }
                List<EvaluateAnswerOld> answerOldList = evaluateAnswerOldMapper.findBySubjectDetailId(recordOld.getSubjectDetailId());
                String answerStr = JSONObject.toJSONString(answerOldList);
                EvaluateRecord record = new EvaluateRecord();
                record.setChildId(recordOld.getChildId());

                record.setCenterId(child.getCenterId());
                record.setEvaluateNumber(evaluateNumber);
                record.setProjectType(1);
                record.setProjectModule(recordOld.getProjectModule());
                /*
                 * 因为在旧数据中其他的有去进行关联这俩没有在表中进行关联，所以这边直接做一下处理
                 * 大类3代表认知力， 大类6
                 */
                if (recordOld.getProjectModule().equals(3)) {
                    record.setEvaluateModule(Integer.valueOf(sysDictDataMapper.findByDictTypeAndLabel("business_evaluate_module_v1", "认知能力")));
                } else if (recordOld.getProjectModule().equals(6)) {
                    record.setEvaluateModule(Integer.valueOf(sysDictDataMapper.findByDictTypeAndLabel("business_evaluate_module_v1", "社交能力")));
                } else {
                    record.setEvaluateModule(Integer.valueOf(sysDictDataMapper.findByDictTypeAndLabel("business_evaluate_module_v1", recordOld.getEvaluateModule())));
                }
                record.setQuestion(recordOld.getQuestion());
                record.setAnswer(answerStr);
                record.setChildAnswer(recordOld.getChildAnswer());
                record.setChildScore(recordOld.getChildScore());
                record.setQuestionMaxScore(4);
                record.setQuestionSort(recordOld.getQuestionSort());
                record.setCreateTime(recordOld.getCreateTime());
                // 因为后续在将原来的测评生成url保存这里，只有用reportId来进行关联，所以在这张表里面也存一份生成的测评编号，方便后面使用
                recordOld.setEvaluateNumber(evaluateNumber);
                evaluateRecordOldMapper.update(recordOld);
                evaluateRecordMapper.insert(record);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void saveOldChildScore() {
        // 查询出原先保存的测评编号与关联的报告id
        List<EvaluateRecordOld> recordOldList = evaluateRecordOldMapper.findEvaluateNumAndReportId();
        Map<Long, String> evaluateNumMap = recordOldList.stream().collect(Collectors.toMap(EvaluateRecordOld::getReportId, EvaluateRecordOld::getEvaluateNumber));
        List<EvaluateScoreNow> evaluateScoreNowList = evaluateScoreNowMapper.findAll();
        for (EvaluateScoreNow evaluateScoreNow : evaluateScoreNowList) {
            EvaluateScore evaluateScore = new EvaluateScore();
            evaluateScore.setChildId(evaluateScoreNow.getChildId());
            evaluateScore.setCenterId(evaluateScoreNow.getCenterId());
            evaluateScore.setProjectType(1);
            evaluateScore.setProjectModule(evaluateScoreNow.getProjectModule());
            evaluateScore.setEvaluateModule(evaluateScoreNow.getEvaluateModule());
            // 根据答题记录中的报告id获取测评编号，如果测评编号为空则代表是异常数据，这里直接将原报告id放到了编号的位置
            evaluateScore.setEvaluateNumber(evaluateNumMap.get(evaluateScoreNow.getReportId()) == null ? evaluateScoreNow.getReportId() + "" : evaluateNumMap.get(evaluateScoreNow.getReportId()));
            evaluateScore.setScore(evaluateScoreNow.getScore().equals("-") ? null : Integer.valueOf(evaluateScoreNow.getScore()));
            evaluateScore.setTotalScore(evaluateScoreNow.getTotalScore().equals("-") ? null : Integer.valueOf(evaluateScoreNow.getTotalScore()));
            evaluateScore.setReportRemark(evaluateScoreNow.getReportRemark());
            evaluateScore.setCreateBy("oldQES");
            evaluateScore.setCreateTime(evaluateScoreNow.getCreateTime());
            evaluateScoreMapper.insert(evaluateScore);
        }
    }

    @Override
    public List<EvaluateRecord> findByChildEvaluateNumber(Long childId,String number,List<Long> questionIds) {
        return  evaluateRecordMapper.selectByChildEvaluateNumber(childId,number,questionIds);
    }

    @Override
    public int getCountByProjectModule(String evaluateNumber, Integer projectModule) {
        return evaluateRecordMapper.getCountByProjectModule(evaluateNumber,projectModule);
    }

    /**
     * 保存题目
     */
    private Boolean saveEvaluateRecord(List<QuestionDTO> questionList, Map<String, QuestionAnswerDTO> questionMap, String teacherName, Child child, String evaluateNumber) {
        List<EvaluateRecord> evaluateRecordList = new ArrayList<>();
        for (QuestionDTO questionDTO : questionList) {
            QuestionAnswerDTO questionAnswerDTO = questionMap.get(questionDTO.getId() + "");
            String childAnswer = "";
            Integer childScore = null;
            if (questionAnswerDTO != null) {
                childAnswer = StringUtils.isEmpty(questionAnswerDTO.getAnswerSore()) ? null : questionAnswerDTO.getAnswerSore();
                childScore = StringUtils.isEmpty(questionAnswerDTO.getAnswerSore()) ? null : Integer.valueOf(questionAnswerDTO.getAnswerSore());
            }
            EvaluateRecord evaluateRecord = new EvaluateRecord();
            evaluateRecord.setQuestionId(questionDTO.getId());
            evaluateRecord.setCenterId(child.getCenterId());
            evaluateRecord.setChildId(child.getId());
            evaluateRecord.setEvaluateNumber(evaluateNumber);
            evaluateRecord.setProjectType(questionDTO.getProjectType());
            evaluateRecord.setProjectModule(questionDTO.getProjectModule());
            evaluateRecord.setEvaluateModule(questionDTO.getEvaluateModule());
            evaluateRecord.setQuestion(questionDTO.getQuestion());
            evaluateRecord.setAnswer(questionDTO.getAnswer());
            evaluateRecord.setQuestionMaxScore(getMaxScore(questionDTO.getAnswer()));
            evaluateRecord.setQuestionSort(questionDTO.getQuestionSort());
            evaluateRecord.setChildAnswer(StringUtils.isNotEmpty(childAnswer) ? childAnswer : null);
            evaluateRecord.setChildScore(childScore);
            evaluateRecord.setCreateBy(teacherName);
            evaluateRecord.setCreateTime(new Date());
            evaluateRecordList.add(evaluateRecord);
        }
        for (EvaluateRecord evaluateRecord : evaluateRecordList) {
            evaluateRecordMapper.insert(evaluateRecord);
        }
        return Boolean.TRUE;
    }

    private Boolean updateEvaluateRecord(List<QuestionAnswerDTO> childAnswerList, Child child, String teacherName, String evaluateNumber) {
        for (QuestionAnswerDTO questionAnswerDTO : childAnswerList) {
            if (!StringUtils.isNumeric(questionAnswerDTO.getQuestionId())) {
                continue;
            }
            if (StringUtils.isNotEmpty(questionAnswerDTO.getAnswerSore())) {
                EvaluateRecord evaluateRecord = evaluateRecordMapper.selectByChildEvaluateNumberQuestionId(child.getId(), evaluateNumber, Long.valueOf(questionAnswerDTO.getQuestionId()));
                evaluateRecord.setChildAnswer(questionAnswerDTO.getAnswerSore());
                evaluateRecord.setChildScore(Integer.valueOf(questionAnswerDTO.getAnswerSore()));
                evaluateRecord.setUpdateBy(teacherName);
                evaluateRecord.setUpdateTime(new Date());
                evaluateRecordMapper.updateById(evaluateRecord);
            }
        }
        return Boolean.TRUE;
    }

    /**
     * 获取答案内最大分值的题目
     *
     * @param answer
     * @return
     */
    private Integer getMaxScore(String answer) {
        Integer maxScore = 0;
        JSONArray jsonArray = JSONArray.parseArray(answer);
        for (int i = 0; i < jsonArray.size(); i++) {
            AnswerDTO answerDTO = JSONObject.parseObject(jsonArray.get(i).toString(), AnswerDTO.class);
            if (Integer.valueOf(answerDTO.getScore()) > maxScore) {
                maxScore = Integer.valueOf(answerDTO.getScore());
            }
        }
        return maxScore;
    }

    private void saveEvaluateReport(Child child, String evaluateNumber, String teacherName) {
        String version = sysConfigService.selectConfigByKey("business.template.version");
        EvaluateReport report = new EvaluateReport();
        report.setCenterId(child.getCenterId());
        report.setChildId(child.getId());
        report.setEvaluateNumber(evaluateNumber);
        report.setStatus(1);
        report.setEvaluateVersion(Integer.valueOf(version));
        report.setCreateBy(teacherName);
        report.setUpdateBy(teacherName);
        report.setCreateTime(new Date());
        report.setUpdateTime(new Date());
        evaluateReportMapper.insert(report);
    }

    public static boolean isNumeric(String str) {
        for (int i = str.length(); --i >= 0; ) {
            int chr = str.charAt(i);
            if (chr < 48 || chr > 57)
                return false;
        }
        return true;
    }


}
